package chen.web.back.client.system;

import chen.web.back.client.FormDataBuilder;
import chen.web.back.client.UrlHelper;

import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
import com.extjs.gxt.ui.client.event.BaseEvent;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.Status;
import com.extjs.gxt.ui.client.widget.TabItem;
import com.extjs.gxt.ui.client.widget.TabPanel;
import com.extjs.gxt.ui.client.widget.VerticalPanel;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.FormPanel;
import com.extjs.gxt.ui.client.widget.form.TextArea;
import com.extjs.gxt.ui.client.widget.layout.ColumnData;
import com.extjs.gxt.ui.client.widget.layout.ColumnLayout;
import com.extjs.gxt.ui.client.widget.layout.FormData;
import com.extjs.gxt.ui.client.widget.layout.FormLayout;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.user.client.Element;

public class FirewallForm extends LayoutContainer {

	@Override
	protected void onRender(Element parent, int index) {
		// TODO Auto-generated method stub
		super.onRender(parent, index);
		VerticalPanel vp = new VerticalPanel();
		vp.add(createTabPanel());
		add(vp);
	}
	
	private TabPanel createTabPanel(){
		final TabPanel tabs = new TabPanel();
	    tabs.add(createTabItem("IpTable",1));
	    tabs.add(createTabItem("UuidTable",2));
	    tabs.add(createTabItem("AccountTable",3));
	    tabs.setSize(500, 600);
	    tabs.setBodyBorder(false);
	    return tabs;
	}
	
	private TabItem createTabItem(String title, int type){
		TabItem item = new TabItem();
		item.setText(title);  
		item.setLayout(new FormLayout());
		final MyFormPanel panel = new MyFormPanel(type);
		panel.saveButton.addSelectionListener(new SelectionListener<ButtonEvent>() {
			public void componentSelected(ButtonEvent ce) {
				saveData(panel);
			}
		});
		item.add(panel);
		loadData(panel);
		return item;
	}
	
	private void saveData(final MyFormPanel panel){
		panel.status.show();
		panel.saveButton.disable();
		RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, UrlHelper.toAbsolute("/config/firewall"));
		builder.setHeader("Content-Type", "application/x-www-form-urlencoded");
		try {
			FormDataBuilder fdb = new FormDataBuilder();
			String value = panel.allow.getValue();
			String[] allowRules = value == null ? new String[1]:value.split("\n"); 
			fdb.setProperty("allowRules", allowRules);
			value = panel.deny.getValue();
			String[] denyRules = value == null ? new String[1]:value.split("\n");
			fdb.setProperty("denyRules", denyRules);
			fdb.addProperty("type", String.valueOf(panel.type));
			fdb.addProperty("_method", "PUT");
			builder.sendRequest(fdb.toQueryString(), new RequestCallback(){

				@Override
				public void onError(Request arg0, Throwable arg1) {
					// TODO Auto-generated method stub
					displayError(panel, "Couldn't retrieve JSON");
				}

				@Override
				public void onResponseReceived(Request request, Response response) {
					// TODO Auto-generated method stub
					if (200 == response.getStatusCode()) {
						JSONValue json = JSONParser.parseStrict(response
								.getText());
						boolean success = json.isObject().get("success").isBoolean().booleanValue();
						if(!success){
							displayError(panel, response.getText());
						} 
						panel.status.hide();
					}  else {
						displayError(panel,"Couldn't retrieve JSON ("
								+ response.getStatusText() + ")");
					}
				}
				
			});
		} catch (RequestException e) {
			// TODO Auto-generated catch block
			displayError(panel,"Couldn't retrieve JSON");
		}
	}
	
	private void loadData(final MyFormPanel panel){
		panel.status.show();
		panel.saveButton.disable();
		RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, UrlHelper.toAbsolute("/config/firewall?type=" + panel.type));
		try {
			builder.sendRequest(null, new RequestCallback(){

				@Override
				public void onError(Request arg0, Throwable arg1) {
					// TODO Auto-generated method stub
					displayError(panel,"Couldn't retrieve JSON");
				}

				@Override
				public void onResponseReceived(Request request, Response response) {
					// TODO Auto-generated method stub
					if (200 == response.getStatusCode()) {
						JSONValue json = JSONParser.parseStrict(response
								.getText());
						JSONObject returnObject = json.isObject().get("returnObject").isObject();
						JSONArray denyRules = returnObject.get("denyRules").isArray();
						panel.denyValue = format(denyRules);
						panel.deny.setValue(panel.denyValue);
						
						JSONArray allowRules = returnObject.get("allowRules").isArray();
						panel.allowValue = format(allowRules);
						panel.allow.setValue(panel.allowValue);
						
						panel.status.hide();
					}  else {
						displayError(panel, "Couldn't retrieve JSON ("
								+ response.getStatusText() + ")");
					}
				}
				
			});
		} catch (RequestException e) {
			// TODO Auto-generated catch block
			displayError(panel, "Couldn't retrieve JSON");
		}
	}
	
	private String format(JSONArray array){
		String value = "";
		for(int i=0; i<array.size(); i++){
			value = value + array.get(i).isString().stringValue() + '\n';
		}		
		return value;
	}
	
	private void displayError(MyFormPanel panel, String message){
		panel.status.hide();
		panel.saveButton.enable();
		MessageBox.alert("出错", message, null);
	}

	private static class MyFormPanel extends FormPanel{
		private int type = 0;
		private TextArea deny = null;
		private TextArea allow = null;
		private Status status = null;
		private Button saveButton = null;
		
		private String denyValue = null;
		private String allowValue = null;
		
		public MyFormPanel(int type){
			this.type = type;
			FormData formData = new FormData("100%");  
		    this.setFrame(true);   
		    this.setHeaderVisible(false);
		    this.setStyleAttribute("borderTop", "none");
		    this.setLabelAlign(LabelAlign.TOP);  
		    this.setButtonAlign(HorizontalAlignment.CENTER);  
			
			
		    LayoutContainer main = new LayoutContainer();  
		    main.setLayout(new ColumnLayout());  
		  
		    LayoutContainer left = new LayoutContainer();  
		    FormLayout layout = new FormLayout();  
		    layout.setLabelAlign(LabelAlign.TOP);  
		    left.setLayout(layout);  
		    left.setStyleAttribute("paddingRight", "10px");  
		    deny = new TextArea();
		    deny.setSize(200, 450);
		    deny.setFieldLabel("deny");
			left.add(deny, formData);
			
		    LayoutContainer right = new LayoutContainer();  
		    layout = new FormLayout();  
		    layout.setLabelAlign(LabelAlign.TOP);  
		    right.setLayout(layout);  
		    right.setStyleAttribute("paddingLeft", "10px");  
		    allow = new TextArea();
		    allow.setSize(200, 450);
		    allow.setFieldLabel("allow");
			right.add(allow, formData);
			
			main.add(left, new ColumnData(.5));
		    main.add(right, new ColumnData(.5));
		    
			this.add(main, new FormData("100%"));
			
			status = new Status();
			status.setBusy("please wait...");
			status.hide();
			status.setAutoWidth(true);
			this.getButtonBar().add(status);
			
			saveButton = new Button("提交");
			Listener<BaseEvent> inputListener = new Listener<BaseEvent>(){
				@Override
				public void handleEvent(BaseEvent be) {
					// TODO Auto-generated method stub
					if(!MyFormPanel.equals(deny.getValue(), denyValue) || !MyFormPanel.equals(allow.getValue(), allowValue)){
						saveButton.enable();
					}
				}
				
			};
			allow.addListener(Events.OnChange, inputListener);
			allow.addListener(Events.OnKeyPress, inputListener);
			deny.addListener(Events.OnChange, inputListener);
			deny.addListener(Events.OnKeyPress, inputListener);
		    this.addButton(saveButton);  
			
		}
		
		private static boolean equals(String a, String b){
			if(a == b) return true;
			if(a == null)	return b.equals(a);
			else return a.equals(b);		}
	}
}
